﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;

namespace PersonaLibrary.Mapping
{
	internal class Mapper
	{
		private static Mapper _instance;
		private static readonly object _loadLock = new object();

		private readonly Dictionary<string, Dictionary<string, string>> _types;
		private readonly Dictionary<string, string> _simpleDictionary;

		private Mapper()
		{
			_types = new Dictionary<string, Dictionary<string, string>>();

			XmlDocument document = new XmlDocument();
			document.Load("Config\\Map.xml");

			XmlNodeList items = document.SelectNodes("root/item");
			foreach (XmlNode item in items)
			{
				if (_simpleDictionary == null)
					_simpleDictionary = new Dictionary<string, string>();

				_simpleDictionary.Add(item.Attributes["name"].Value, item.FirstChild.Value);
			}

			XmlNodeList types = document.SelectNodes("root/type");
			foreach (XmlNode type in types)
			{
				Dictionary<string, string> itemsType;
				_types.TryGetValue(type.Attributes["name"].Value, out itemsType);
				if (itemsType == null)
				{
					itemsType = new Dictionary<string, string>();
					_types.Add(type.Attributes["name"].Value, itemsType);
				}

				foreach (XmlNode childNode in type.ChildNodes)
				{
					itemsType.Add(childNode.Attributes["name"].Value, childNode.FirstChild.Value);
				}
			}
		}

		public static Mapper Instance
		{
			get
			{
				if (_instance == null)
				{
					lock (_loadLock)
					{
						if (_instance == null)
						{
							_instance = new Mapper();
						}
					}
				}
				return _instance;
			}
		}

		public string Convert(string value)
		{
			string result;
			if (_simpleDictionary.TryGetValue(value, out result))
				return result;
			else
			{
				string key = _simpleDictionary.FirstOrDefault(x => x.Value == value).Key;
				if (!string.IsNullOrEmpty(key))
					return key;
			}

			result = _types.SingleOrDefault(type => type.Value.Any(item => item.Key == value)).Value.SingleOrDefault(x => x.Key == value).Value;

			if (!string.IsNullOrEmpty(result))
				return result;

			return value;
		}

		public string Convert(string value, string type)
		{
			if(!TryConvert(value, type))
				return value;

			string result = _types.SingleOrDefault(x => x.Key == type).Value.SingleOrDefault(x => x.Key == value).Value;

			if (!string.IsNullOrEmpty(result))
				return result;

			if (_simpleDictionary.TryGetValue(value, out result))
				return result;

			return value;
		}

		public bool TryConvert(string value)
		{
			bool result = _simpleDictionary.ContainsKey(value);

			if(result)
				return result;

			result = _types.SingleOrDefault(type => type.Value.Any(item => item.Key == value)).Value.Any(x => x.Key == value);

			return result;
		}

		public bool TryConvert(string value, string type)
		{
			Dictionary<string, string> singleOrDefault = _types.SingleOrDefault(x => x.Key == type).Value;
			if(singleOrDefault == null)
				return false;

			bool result = singleOrDefault.Any(x => x.Key == value);

			if (result)
				return result;

			return _simpleDictionary.ContainsKey(value);
		}
	}
}
